﻿using System.Reflection;
using System.Text.Json;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using Vin.Event;
using Vin.Extension.SqlSugar.Attributes;
using Vin.Extension.SqlSugar.EventArgs;
using Vin.Extension.SqlSugar.Extension;
using Vin.Extension.SqlSugar.Models;
using Vin.Extension.SqlSugar.Options;
using Vin.Extension.SqlSugar.Repository;
using Vin.Extension.SqlSugar.SugarFilter;
using Vin.Tool.AspNetCore.Extension;
using Vin.Tool.AspNetCore.Singleton;
using Vin.Tool.Core.AssemblyCategory;
using Vin.Tool.Core.ConvertCategory;
using Vin.Tool.Domain.SystemModel;


namespace Vin.Extension.SqlSugar;

public static class VinSqlSugarExtension
{
    public const string OptionKey = "VinSql:SqlSugar";

    public static readonly SqlSugarConfig SqlSugarConfig = new();

    private static ConnectionConfig GetConnectionConfig()
    {
        var config = new ConnectionConfig()
        {
            ConnectionString = SqlSugarConfig.SqlSugarOption!.Connection,
            DbType = (DbType)SqlSugarConfig.SqlSugarOption.SqlType,
            IsAutoCloseConnection = true,
            InitKeyType = InitKeyType.Attribute,
            ConfigureExternalServices = new ConfigureExternalServices()
            {
                // 处理属性名
                EntityService = (property, column) =>
                {
                    column.DbColumnName = UtilMethods.ToUnderLine(column.DbColumnName);

                    // 如果是Json类型并且是mysql，则设置为json
                    if (column.IsJson && SqlSugarConfig.SqlSugarOption.SqlType == (int)DbType.MySql)
                    {
                        column.DataType = "json";
                    }

                    #region 如果是枚举，则在描述中拼接枚举值

                    // {
                    //     Type? enumType = null;
                    //     if (property.PropertyType.IsGenericType &&
                    //         property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                    //     {
                    //         var underlyingType = Nullable.GetUnderlyingType(property.PropertyType);
                    //         if (underlyingType != null && underlyingType.IsEnum)
                    //         {
                    //             enumType = underlyingType;
                    //         }
                    //     }
                    //     else
                    //     {
                    //         enumType = property.PropertyType.IsEnum ? property.PropertyType : null;
                    //     }
                    //
                    //     if (enumType != null)
                    //     {
                    //         column.ColumnDescription = column.ColumnDescription + " " +
                    //                                    string.Join(",", Enum.GetValues(enumType).Cast<Enum>()
                    //                                        .Select(m => $"{m.ToInt()}={m}"));
                    //     }
                    // }

                    #endregion
                },
                // 处理表名
                EntityNameService = (type, table) =>
                {
                    table.IsCreateTableFiledSort = true;
                    table.DbTableName = UtilMethods.ToUnderLine(table.DbTableName);
                }
            }
        };

        // 添加内置的SqlFunc
        config.ConfigureExternalServices.SqlFuncServices ??= new List<SqlFuncExternal>();
        config.ConfigureExternalServices.SqlFuncServices.AddRange(VinSqlFuncManager.SqlFuncExtensions);

        return config;
    }

    /// <summary>
    /// 获取动态添加注入的表
    /// </summary>
    private static readonly List<Func<List<Type>>> InjectInitTables = new();

    public static void AddInjectTablesProvider(Func<List<Type>> injectFunc) =>
        InjectInitTables.Add(injectFunc);

    public static void AddSqlSugarClient(this IServiceCollection services)
    {
        SqlSugarConfig.SqlSugarOption = VinApp.Configuration.GetSection(OptionKey).Get<SqlSugarOption>();
        if (SqlSugarConfig.SqlSugarOption == null)
        {
            Console.WriteLine($"{OptionKey}配置错误，请检查是否已经配置了{OptionKey}节点");
            return;
        }

        // 注入仓储
        services.AddScoped(typeof(VinBaseRepository<>));

        var allCustomRepository = AssemblyTool.GetTypesByAttribute<VinRepositoryAttribute>().Select(m =>
        {
            var attr = m.GetCustomAttribute<VinRepositoryAttribute>()!;
            return new RegisterModel()
            {
                Type = m,
                Order = attr.Order,
                Lifetime = attr.Lifetime
            };
        }).OrderBy(m => m.Order).ToList();
        services.AddRegisterModelExtension(allCustomRepository);

        // 注入SqlSugarClient
        services.AddScoped<ISqlSugarClient>((_) =>
        {
            return new VinSqlSugarClient(GetConnectionConfig(), (db) =>
            {
                // 添加内置的过滤器
                db.QueryFilter.AddTableFilter<IDeleted>(m => m.IsDeleted == false);
                // 添加加解密配置
                db.AddEncrypt();
                // 添加插入自动设置主键
                db.AddAutoPrimaryKey();
                // 通知事件
                VinEventManager.Fire<VinSqlSugarInstanceEventArg>(null, new VinSqlSugarInstanceEventArg(db));
            });
        });
    }

    /// <summary>
    /// 初始化表
    /// </summary>
    /// <returns></returns>
    public static Task InitTables()
    {
        return Task.Run(() =>
        {
            var scope = VinApp.ServiceProvider.CreateScope();
            var sqlSugarClient = scope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
            // 判断是否第一次初始化数据库
            var firstInitDatabase = !sqlSugarClient.Ado.IsValidConnection();
            if (!firstInitDatabase && sqlSugarClient.DbMaintenance.GetTableInfoList(false).Count <= 0)
            {
                firstInitDatabase = true;
            }

            sqlSugarClient.DbMaintenance.CreateDatabase();

            var types = AssemblyTool.GetTypesByAttribute<VinSqlSugarEntityAttribute>();
            // 动态添加注入的表
            foreach (var injectInitTable in InjectInitTables)
            {
                types.AddRange(injectInitTable());
            }

            sqlSugarClient.CodeFirst.InitTables(types.ToArray());

            // 触发第一次创建数据库
            if (firstInitDatabase)
            {
                VinEventManager.Fire<VinSqlSugarFirstCreateDatabaseEventArg>(null,
                    new VinSqlSugarFirstCreateDatabaseEventArg());
            }
        });
    }
}